#include "qe_log.h"
#include "qe_list.h"
#include "qe_string.h"
#include "qe_assert.h"
#include "qe_gpio.h"



QELOG_DOMAIN("qe-gpio");

QE_LIST_INIT(gpio_list);

qe_ret qe_gpio_direction_input(qe_gpio_dev *gpio, qe_uint pin)
{
    return gpio->ops->direction_input(gpio, pin);
}

qe_ret qe_gpio_direction_output(qe_gpio_dev *gpio, qe_uint pin, qe_int value)
{
    return gpio->ops->direction_output(gpio, pin, value);
}

qe_ret qe_gpio_set_value(qe_gpio_dev *gpio, qe_uint pin, qe_int value)
{
    return gpio->ops->set_value(gpio, pin, value);
}

qe_int qe_gpio_get_value(qe_gpio_dev *gpio, qe_uint pin)
{
    return gpio->ops->get_value(gpio, pin);
}

static qe_ret gpio_ioctl(qe_dev *dev, qe_int cmd, qe_ptr args)
{
    qe_gpio_dev *gpio = (qe_gpio_dev *)dev->priv;
    
    switch (cmd) {
    
    case QE_GPIO_IOC_SHOW:
        if (gpio->ops->show) {
            gpio->ops->show(gpio);
            return qe_ok;
        } else {
            qe_warning("%s not support show", dev->name);
            return qe_err_notsupport;
        }


    case QE_GPIO_IOC_DUMP_REGISTERS:
        if (gpio->ops->dump_regs) {
            gpio->ops->dump_regs(gpio);
            return qe_ok;
        } else {
            qe_warning("%s not support dump regs", dev->name);
            return qe_err_notsupport;
        }

    case QE_GPIO_IOC_LIST_PINS:
        if (gpio->ops->list_pins) {
            gpio->ops->list_pins(gpio);
            return qe_ok;
        } else {
            qe_warning("%s not support list pins", dev->name);
            return qe_err_notsupport;
        }

    default:
        qe_error("unknown cmd %d", cmd);
        return qe_err_notsupport;
    }
}

static qe_dev_ops gpio_ops = {
    .ioctl = gpio_ioctl,
};

qe_ret qe_gpio_register(qe_gpio_dev *gpio, qe_const_str name, 
    const qe_gpio_ops *ops, void *priv)
{
    qe_dev *dev;

    dev = &gpio->parent;
    
    dev->type = QE_DEV_GPIO;
    dev->rx_indicate = QE_NULL;
    dev->tx_complete = QE_NULL;
    dev->ops = &gpio_ops;
    dev->priv = priv;

    gpio->ops = ops;

    qe_list_append(&gpio->list, &gpio_list);

    return qe_dev_register(dev, name, 0x0);
}

void qe_gpio_list_devices(void)
{
    qe_gpio_dev *p;

    qe_list_foreach_entry(p, &gpio_list, list) {
        qe_printf("%s\r\n", p->parent.name);
    }
}